package org.wattdepot.gdata.kukuicup.updater;

import java.util.ArrayList;
import java.util.List;
import org.wattdepot.gdata.kukuicup.service.GDataService;
import org.wattdepot.gdata.kukuicup.service.GDataView;

/**
 * Enables clients to obtain a read-only view of a daily or hourly energy baseline spreadsheet.
 * @author Philip Johnson
 */
public class BaselineView {
  
  /** The GDataService for this run. */
  private GDataService gdataService;
  /** The abstraction violation.  This class must know the spreadsheet name. */
  private String hourlyBaselineSpreadsheetName = "HourlyEnergyBaselines";
  /** The abstraction violation.  This class must know the spreadsheet name. */
  private String dailyBaselineSpreadsheetName = "DailyEnergyBaselines";
  /** The cached view of the hourly baselines spreadsheet. */
  private GDataView hourlyView = null;
  /** The cached view of the daily baselines spreadsheet. */
  private GDataView dailyView = null;

  /**
   * Creates a new BaselineView given the service. 
   * @param gdataService The service. 
   */
  public BaselineView(GDataService gdataService) {
    this.gdataService = gdataService;
  }
  
  /**
   * Return a view of the hourly baselines spreadsheet.
   * @return The hourly baselines spreadsheet.
   * @throws RuntimeException If this can't be done. 
   */
  private GDataView getHourlyBaselineView() {
    if (hourlyView != null) {
      return hourlyView;
    }
    // Otherwise get the view and cache it.
    try { 
      hourlyView = new GDataView(this.gdataService, 
        this.gdataService.getSpreadsheetURL(this.hourlyBaselineSpreadsheetName));
      return hourlyView;
    }
    catch (Exception e) {
      throw new RuntimeException("Couldn't get" + this.hourlyBaselineSpreadsheetName, e);
    }
  }
  
  /**
   * Return a view of the hourly baselines spreadsheet.
   * @return The hourly baselines spreadsheet.
   * @throws RuntimeException If this can't be done. 
   */
  private GDataView getDailyBaselineView() {
    if (dailyView != null) {
      return dailyView;
    }
    // Otherwise get the view and cache it.
    try { 
      dailyView = new GDataView(this.gdataService, 
        this.gdataService.getSpreadsheetURL(this.dailyBaselineSpreadsheetName));
      return dailyView;
    }
    catch (Exception e) {
      throw new RuntimeException("Couldn't get" + this.dailyBaselineSpreadsheetName, e);
    }
  }
  
  /**
   * Returns a list of 24 hourly baseline data values starting with the specified start day. 
   * @param sourceName The source whose baselines we're interested in.
   * @param startDay The start day, from 1 to 7, using Calendar.DAY_OF_WEEK.
   * @return The list of baseline data in order from hour 0 to hour 23.
   */
  public List<Integer> getHourlyBaselines(String sourceName, int startDay) {
    GDataView view = getHourlyBaselineView();
    int row = view.findRow(sourceName); 
    List<String> rowData = view.getCellData(view.getRow(row));
    List<Integer> baselines = new ArrayList<Integer>();
    // Make day of week zero-based, then multiply by 24 and offset by 5 to get start column.
    int startColumn = ((startDay - 1) * 24) + 4;
    // Get the 24 hours of hourly data.
    for (int i = 0; i < 24; i++) {
      baselines.add(Integer.valueOf(rowData.get(i + startColumn)));
    }
    return baselines;
  }
  
  /**
   * Returns a list of 7 daily baseline data values starting with the specified start day. 
   * @param sourceName The source whose baselines we're interested in.
   * @param startDay The start day, from 1 to 7.
   * @return The list of baseline data in order from n to 7 and 1 to n - 1.
   */
  public List<String> getDailyBaselines(String sourceName, int startDay) {
    GDataView view = getDailyBaselineView();
    int row = view.findRow(sourceName); 
    List<String> rowData = view.getCellData(view.getRow(row));
    List<String> baselines = new ArrayList<String>();
    int startColumn = startDay + 3;
    // Get the first section from startDay through day 7.
    for (int i = startColumn; i < 11; i++) {
      baselines.add(rowData.get(i));
    }
    // Now get the remaining from 1 to startDay - 1.
    for (int i = 1; i < startDay; i++) {
      baselines.add(rowData.get(i + 3));
    }
    return baselines;
  }
}
